package com.yesep.learn.design.behavioral.chain_of_responsibility.engine;

/**
 * 责任链抽象处理者
 */
public abstract class IChainHandler<R extends IChainRequest> {

    /**
     * 唯一标志
     */
    private String key;
    /**
     * 下一节点
     */
    private IChainHandler<R> next;

    public IChainHandler() {
        this.key = this.getClass().getName();
    }


    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public IChainHandler<R> getNext() {
        return next;
    }

    public IChainHandler<R> setNext(IChainHandler<R> next) {
        this.next = next;
        return next;
    }

    protected boolean isStart() {
        return this instanceof IStartHandler;
    }

    protected boolean isEnd() {
        return this instanceof IEndHandler;
    }

    /**
     * 启动责任链
     *
     * @param context 责任链上下文
     */
    public final void startup(ChainContext<R> context) {
        process(context, ChainRoute.STARTUP);
        updateNextHandler(context);
    }

    /**
     * 终止责任链
     *
     * @param context 责任链上下文
     */
    public final void terminate(ChainContext<R> context) {
        context.getPayload().setComment(null);
        process(context, ChainRoute.TERMINATE);
        context.clearHandlerKey();//最后结点
    }

    /**
     * 责任链向前
     *
     * @param context 责任链上下文
     */
    public final void forward(ChainContext<R> context) {
        process(context, ChainRoute.FORWARD);
        updateNextHandler(context);
    }

    private void updateNextHandler(ChainContext<R> context) {
        IChainHandler<R> nextHandler = getNext();
        if (null != nextHandler) {
            context.setHandlerKey(nextHandler.getKey());
            if (nextHandler.isEnd()) {//下个结点是结束节点，直接执行
                nextHandler.terminate(context);
            }
        } else {//责任链结束
            context.clearHandlerKey();//最后结点
            //System.out.printf("End of chain. No more handlers after %s.\n", this.getKey());
        }
    }


    /**
     * 责任链向后
     *
     * @param context 责任链上下文
     */
    public final void backward(ChainContext<R> context) {
        String error = String.format("Already at the start of the chain at %s.\n", this.getKey());
        if (isStart()) {//启动节点，不能后退
            throw new IllegalStateException(error);
        }
        process(context, ChainRoute.BACKWARD);
        IChainHandler<R> previousHandler = context.getPreviousHandler();
        if (null != previousHandler) {
            context.setHandlerKey(previousHandler.getKey());
        } else {
            throw new IllegalStateException(error);
        }
    }

    /**
     * 责任链跳转
     *
     * @param context 责任链上下文
     */
    public final void custom(ChainContext<R> context) {
        process(context, ChainRoute.CUSTOM);
    }

    /**
     * 责任链处理
     *
     * @param context 责任链上下文
     */
    public final void handle(ChainContext<R> context, ChainRoute direction) {
        switch (direction) {
            case STARTUP:
                startup(context);
                break;
            case FORWARD:
                forward(context);
                break;
            case BACKWARD:
                backward(context);
                break;
            case CUSTOM:
                custom(context);
                break;
            case TERMINATE:
                terminate(context);
                break;
        }
    }

    // 责任链处理
    public void process(ChainContext<R> context, ChainRoute direction) {
        System.out.printf("%s %s processing request for %s :  %s   %s\n",
                this.getClass().getSimpleName(), context.getPayload().getUserName(),
                context.getRequest().getActor().getUserName(), direction, context.getPayload().getComment());
    }
}
